﻿// //  ********************************************************************************
// //  Copyright (C) 2016 Sebastian Kenter. All rights reserved.
// // 
// //  Name    : MultiServerEngine | LoginServer | RegisterSubServerResponseHandler.cs
// //  Created : 2016 - 02 - 16 20:53
// //  Modified: 2016 - 02 - 20 12:33
// //  ********************************************************************************

using ExitGames.Logging;
using NHibernate;
using ServerFramework.Implementation.Database;
using ServerFramework.Implementation.Database.Domain;
using ServerFramework.Implementation.Handler;
using ServerFramework.Implementation.Operations.Response;
using ServerFramework.Implementation.Server;
using ServerFramework.Implementation.Telegram;
using ServerFramework.Interfaces.Server;
using ServerFramework.Interfaces.Telegram;
using TypeDefs;

namespace LoginServer.Handler.Response
{
    public class RegisterSubServerResponseHandler : ServerTelegramHandler
    {
        private IServerPeerRegistry<IServerPeer> ServerPeerRegistry { get; }
        public override TelegramHandlerTypes HandlerType => TelegramHandlerTypes.Response;
        public override byte Code => (byte) OperationCodes.System;
        public override int? SubCode => (int?) OperationSubCodes.RegisterSubServer;

        public RegisterSubServerResponseHandler(ILogger logger, IServerPeerRegistry<IServerPeer> serverPeerRegistry)
            : base(logger)
        {
            ServerPeerRegistry = serverPeerRegistry;
        }

        public override bool HandleTelegram(ITelegram telegram, IServerPeer serverPeer)
        {
            Logger.InfoFormat("Trying to handle telegram of type={0}, code={1}, sub-code={2}", telegram.Type,
                telegram.Code, telegram.SubCode);

            ServerPeer peer = serverPeer as ServerPeer;

            if (peer != null)
            {
                ResponseTelegram response = telegram as ResponseTelegram;

                if (response != null && response.ReturnCode == (short) ErrorCodes.Ok)
                {
                    RegisterSubServerResponseOperation contract = new RegisterSubServerResponseOperation(peer.Protocol,
                        telegram);

                    if (!contract.IsValid)
                    {
                        string msg = contract.GetErrorMessage();
                        Logger.ErrorFormat("Server peer register response invalid ({0})", msg);
                    }
                    Logger.DebugFormat("Operation successful. Registering peer as {0} on {1}",
                        (ServerTypes) contract.PeerType, peer.ServerType);

                    if (!ServerPeerRegistry.RegisterPeer((ServerTypes) contract.PeerType, peer)) return false;

                    using (ISession session = SessionManager.OpenSession())
                    {
                        using (ITransaction transaction = session.BeginTransaction())
                        {
                            var sp = (ServerPeer)serverPeer;

                            var speer = new ServerPeer_T
                            {
                                Connected = 1,
                                Localip = sp.LocalIP,
                                Localport = sp.LocalPort,
                                Localservertype = (int)sp.ServerType,
                                Remoteip = sp.RemoteIP,
                                Remoteport = sp.RemotePort,
                                Remoteservertype = contract.PeerType,
                                Peerid = sp.PeerId.ToString()
                            };

                            if (!session.QueryOver<ServerPeer_T>().List<ServerPeer_T>().Contains(speer))
                            {
                                session.Save(speer);
                            }

                            transaction.Commit();
                        }

                        session.Close();
                    }
                }
            }

            return true;
        }
    }
}
